Bahasa Indonesia

Jelajahi Rute API Next.js dan buka kemampuan pengembangan full-stack dalam aplikasi React Anda. Pelajari pola, praktik terbaik, dan strategi deployment.

Rute API Next.js: Pola Pengembangan Full-Stack

Next.js telah merevolusi pengembangan React dengan menyediakan kerangka kerja yang kuat untuk membangun aplikasi web yang berkinerja dan dapat diskalakan. Salah satu fitur utamanya adalah Rute API, yang memungkinkan pengembang untuk membuat fungsionalitas backend langsung di dalam proyek Next.js mereka. Pendekatan ini merampingkan pengembangan, menyederhanakan deployment, dan membuka kemampuan full-stack yang kuat.

Apa itu Rute API Next.js?

Rute API Next.js adalah fungsi serverless yang ditulis langsung di dalam direktori /pages/api Anda. Setiap file di direktori ini menjadi sebuah endpoint API, yang secara otomatis mengarahkan permintaan HTTP ke fungsi yang sesuai. Ini menghilangkan kebutuhan akan server backend terpisah, menyederhanakan arsitektur aplikasi Anda dan mengurangi overhead operasional.

Anggaplah ini sebagai fungsi serverless mini yang ada di dalam aplikasi Next.js Anda. Mereka merespons permintaan HTTP seperti GET, POST, PUT, DELETE, dan dapat berinteraksi dengan database, API eksternal, dan sumber daya sisi server lainnya. Yang terpenting, mereka hanya berjalan di server, bukan di browser pengguna, sehingga menjamin keamanan data sensitif seperti kunci API.

Manfaat Utama Rute API

Memulai dengan Rute API

Membuat rute API di Next.js sangatlah mudah. Cukup buat file baru di dalam direktori /pages/api. Nama file akan menentukan path rute tersebut. Misalnya, membuat file bernama /pages/api/hello.js akan membuat endpoint API yang dapat diakses di /api/hello.

Contoh: API Sapaan Sederhana

Berikut adalah contoh dasar rute API yang mengembalikan respons JSON:


// pages/api/hello.js

export default function handler(req, res) {
  res.status(200).json({ message: 'Halo dari Rute API Next.js!' });
}

Kode ini mendefinisikan fungsi asinkron handler yang menerima dua argumen:

Fungsi ini mengatur kode status HTTP ke 200 (OK) dan mengembalikan respons JSON dengan sebuah pesan.

Menangani Metode HTTP yang Berbeda

Anda dapat menangani metode HTTP yang berbeda (GET, POST, PUT, DELETE, dll.) di dalam rute API Anda dengan memeriksa properti req.method. Ini memungkinkan Anda untuk membuat API RESTful dengan mudah.


// pages/api/todos.js

export default async function handler(req, res) {
  if (req.method === 'GET') {
    // Ambil semua todo dari database
    const todos = await fetchTodos();
    res.status(200).json(todos);
  } else if (req.method === 'POST') {
    // Buat todo baru
    const newTodo = await createTodo(req.body);
    res.status(201).json(newTodo);
  } else {
    // Tangani metode yang tidak didukung
    res.status(405).json({ message: 'Metode Tidak Diizinkan' });
  }
}

Contoh ini menunjukkan cara menangani permintaan GET dan POST untuk endpoint hipotetis /api/todos. Ini juga mencakup penanganan kesalahan untuk metode yang tidak didukung.

Pola Pengembangan Full-Stack dengan Rute API

Rute API Next.js memungkinkan berbagai pola pengembangan full-stack. Berikut adalah beberapa kasus penggunaan umum:

1. Pengambilan dan Manipulasi Data

Rute API dapat digunakan untuk mengambil data dari database, API eksternal, atau sumber data lainnya. Mereka juga dapat digunakan untuk memanipulasi data, seperti membuat, memperbarui, atau menghapus catatan.

Contoh: Mengambil Data Pengguna dari Database


// pages/api/users/[id].js
import { query } from '../../../lib/db';

export default async function handler(req, res) {
  const { id } = req.query;

  try {
    const results = await query(
      'SELECT * FROM users WHERE id = ?',
      [id]
    );

    if (results.length === 0) {
      return res.status(404).json({ message: 'Pengguna tidak ditemukan' });
    }

    res.status(200).json(results[0]);
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Kesalahan Server Internal' });
  }
}

Contoh ini mengambil data pengguna dari database berdasarkan ID pengguna yang diberikan di URL. Ini menggunakan pustaka kueri database (diasumsikan berada di lib/db) untuk berinteraksi dengan database. Perhatikan penggunaan kueri berparameter untuk mencegah kerentanan injeksi SQL.

2. Autentikasi dan Otorisasi

Rute API dapat digunakan untuk mengimplementasikan logika autentikasi dan otorisasi. Anda dapat menggunakannya untuk memverifikasi kredensial pengguna, menghasilkan token JWT, dan melindungi sumber daya sensitif.

Contoh: Autentikasi Pengguna


// pages/api/login.js
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { query } from '../../lib/db';

export default async function handler(req, res) {
  if (req.method === 'POST') {
    const { email, password } = req.body;

    try {
      const results = await query(
        'SELECT * FROM users WHERE email = ?',
        [email]
      );

      if (results.length === 0) {
        return res.status(401).json({ message: 'Kredensial tidak valid' });
      }

      const user = results[0];

      const passwordMatch = await bcrypt.compare(password, user.password);

      if (!passwordMatch) {
        return res.status(401).json({ message: 'Kredensial tidak valid' });
      }

      const token = jwt.sign(
        { userId: user.id, email: user.email },
        process.env.JWT_SECRET,
        { expiresIn: '1h' }
      );

      res.status(200).json({ token });
    } catch (error) {
      console.error(error);
      res.status(500).json({ message: 'Kesalahan Server Internal' });
    }
  } else {
    res.status(405).json({ message: 'Metode Tidak Diizinkan' });
  }
}

Contoh ini mengautentikasi pengguna dengan membandingkan kata sandi yang diberikan dengan kata sandi yang telah di-hash di database. Jika kredensial valid, ia menghasilkan token JWT dan mengembalikannya ke klien. Klien kemudian dapat menggunakan token ini untuk mengautentikasi permintaan berikutnya.

3. Penanganan Formulir dan Pengiriman Data

Rute API dapat digunakan untuk menangani pengiriman formulir dan memproses data yang dikirim dari klien. Ini berguna untuk membuat formulir kontak, formulir pendaftaran, dan elemen interaktif lainnya.

Contoh: Pengiriman Formulir Kontak


// pages/api/contact.js
import { sendEmail } from '../../lib/email';

export default async function handler(req, res) {
  if (req.method === 'POST') {
    const { name, email, message } = req.body;

    try {
      await sendEmail({
        to: 'admin@example.com',
        subject: 'Kiriman Formulir Kontak Baru',
        text: `Nama: ${name}\nEmail: ${email}\nPesan: ${message}`,
      });

      res.status(200).json({ message: 'Email berhasil dikirim' });
    } catch (error) {
      console.error(error);
      res.status(500).json({ message: 'Gagal mengirim email' });
    }
  } else {
    res.status(405).json({ message: 'Metode Tidak Diizinkan' });
  }
}

Contoh ini menangani pengiriman formulir kontak dengan mengirim email ke administrator. Ini menggunakan pustaka pengiriman email (diasumsikan berada di lib/email) untuk mengirim email. Anda harus mengganti admin@example.com dengan alamat email penerima yang sebenarnya.

4. Webhook dan Penanganan Event

Rute API dapat digunakan untuk menangani webhook dan merespons event dari layanan eksternal. Ini memungkinkan Anda untuk mengintegrasikan aplikasi Next.js Anda dengan platform lain dan mengotomatiskan tugas.

Contoh: Menangani Webhook Stripe


// pages/api/stripe-webhook.js
import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

export const config = {
  api: {
    bodyParser: false, // Nonaktifkan parsing body default
  },
};

async function buffer(req) {
  const chunks = [];
  for await (const chunk of req) {
    chunks.push(chunk);
  }
  return Buffer.concat(chunks).toString();
}

export default async function handler(req, res) {
  if (req.method === 'POST') {
    const sig = req.headers['stripe-signature'];

    let event;

    try {
      const buf = await buffer(req);
      event = stripe.webhooks.constructEvent(buf, sig, process.env.STRIPE_WEBHOOK_SECRET);
    } catch (err) {
      console.log(`Kesalahan Webhook: ${err.message}`);
      res.status(400).send(`Kesalahan Webhook: ${err.message}`);
      return;
    }

    // Tangani event
    switch (event.type) {
      case 'payment_intent.succeeded':
        const paymentIntent = event.data.object;
        console.log(`PaymentIntent untuk ${paymentIntent.amount} berhasil!`);
        // Kemudian definisikan dan panggil metode untuk menangani payment intent yang berhasil.
        // handlePaymentIntentSucceeded(paymentIntent);
        break;
      case 'payment_method.attached':
        const paymentMethod = event.data.object;
        // Kemudian definisikan dan panggil metode untuk menangani lampiran PaymentMethod yang berhasil.
        // handlePaymentMethodAttached(paymentMethod);
        break;
      default:
        // Tipe event tidak terduga
        console.log(`Tipe event yang tidak ditangani ${event.type}.`);
    }

    // Kembalikan respons 200 untuk mengonfirmasi penerimaan event
    res.status(200).json({ received: true });
  } else {
    res.setHeader('Allow', 'POST');
    res.status(405).end('Metode Tidak Diizinkan');
  }
}

Contoh ini menangani webhook Stripe dengan memverifikasi tanda tangan dan memproses data event. Ini menonaktifkan parser body default dan menggunakan fungsi buffer kustom untuk membaca body permintaan mentah. Sangat penting untuk menonaktifkan parser body default karena Stripe memerlukan body mentah untuk verifikasi tanda tangan. Ingatlah untuk mengonfigurasi endpoint webhook Stripe Anda di dasbor Stripe Anda dan mengatur variabel lingkungan STRIPE_WEBHOOK_SECRET.

Praktik Terbaik untuk Rute API

Untuk memastikan kualitas dan kemudahan pemeliharaan Rute API Anda, ikuti praktik terbaik berikut:

1. Modularisasi Kode Anda

Hindari menulis rute API yang besar dan monolitik. Sebaliknya, pecah kode Anda menjadi modul-modul yang lebih kecil dan dapat digunakan kembali. Ini membuat kode Anda lebih mudah dipahami, diuji, dan dipelihara.

2. Terapkan Penanganan Kesalahan

Tangani kesalahan dengan benar di rute API Anda. Gunakan blok try...catch untuk menangkap pengecualian dan mengembalikan respons kesalahan yang sesuai ke klien. Catat (log) kesalahan untuk membantu debugging dan pemantauan.

3. Validasi Data Input

Selalu validasi data input dari klien untuk mencegah kerentanan keamanan dan memastikan integritas data. Gunakan pustaka validasi seperti Joi atau Yup untuk mendefinisikan skema validasi dan memberlakukan batasan data.

4. Lindungi Data Sensitif

Simpan data sensitif, seperti kunci API dan kredensial database, di variabel lingkungan. Jangan pernah menyimpan data sensitif ke repositori kode Anda.

5. Terapkan Pembatasan Laju (Rate Limiting)

Lindungi rute API Anda dari penyalahgunaan dengan menerapkan pembatasan laju (rate limiting). Ini membatasi jumlah permintaan yang dapat dibuat oleh klien dalam periode waktu tertentu. Gunakan pustaka pembatasan laju seperti express-rate-limit atau limiter.

6. Amankan Kunci API

Jangan mengekspos kunci API secara langsung di kode sisi klien. Selalu proksi permintaan melalui rute API Anda untuk melindungi kunci API Anda dari akses yang tidak sah. Simpan kunci API dengan aman di variabel lingkungan di server Anda.

7. Gunakan Variabel Lingkungan

Hindari menulis nilai konfigurasi secara langsung (hardcoding) di kode Anda. Sebaliknya, gunakan variabel lingkungan untuk menyimpan pengaturan konfigurasi. Ini memudahkan pengelolaan aplikasi Anda di lingkungan yang berbeda (pengembangan, staging, produksi).

8. Pencatatan (Logging) dan Pemantauan

Terapkan pencatatan dan pemantauan untuk melacak kinerja rute API Anda. Catat event penting, seperti kesalahan, peringatan, dan permintaan yang berhasil. Gunakan alat pemantauan untuk melacak metrik seperti latensi permintaan, tingkat kesalahan, dan penggunaan sumber daya. Layanan seperti Sentry, Datadog, atau New Relic dapat membantu.

Pertimbangan Deployment

Rute API Next.js dirancang untuk di-deploy di platform serverless. Opsi deployment yang populer meliputi:

Saat men-deploy aplikasi Next.js Anda dengan Rute API, pastikan variabel lingkungan Anda dikonfigurasi dengan benar di platform deployment. Juga, pertimbangkan waktu cold start dari fungsi serverless, yang dapat memengaruhi waktu respons awal rute API Anda. Mengoptimalkan kode Anda dan menggunakan teknik seperti provisioned concurrency dapat membantu mengurangi masalah cold start.

Kesimpulan

Rute API Next.js menyediakan cara yang kuat dan nyaman untuk membangun aplikasi full-stack dengan React. Dengan memanfaatkan fungsi serverless, Anda dapat menyederhanakan pengembangan, mengurangi overhead operasional, dan meningkatkan performa aplikasi. Dengan mengikuti praktik terbaik yang diuraikan dalam artikel ini, Anda dapat membuat Rute API yang tangguh dan mudah dipelihara yang memberdayakan aplikasi Next.js Anda.

Baik Anda membangun formulir kontak sederhana atau platform e-commerce yang kompleks, Rute API Next.js dapat membantu Anda merampingkan proses pengembangan dan memberikan pengalaman pengguna yang luar biasa.

Pembelajaran Lebih Lanjut